<?php

class tpl{


	## 模板名称
 	private $TplPath=null;
 	
 	## 模板内容
 	private $TplSource=null;
 	
 	## 编译目录
 	private $TplCompile=null;
 	
 	public function __construct(){
 		
 		//$this->TplCompile=APPROOT.'/'.TEMPLATEDIR.'/'.$path.'.php';
 	}
 	
 	/**
 	 * 解析模板时的错误信息
 	 * @param unknown_type $msg
 	 */
 	private function error($msg){
 		ob_clean();
 		header("Content-type: text/html;charset=utf-8");
 		die($msg);	
 	}
 	
 	/**
 	 * 读取内容
 	 * @param $path
 	 */
 	private function readfile($path){
 		
 		$fp = fopen($path, 'r');
 		$line = '';
 			if(filesize($path)>1000){
	 			while (!feof($fp)) {
	 		 		$line .= fgets($fp);
	 			}
	 		}else{	
				$line=fread($fp,filesize($path));
	 		}
	 	fclose($fp);
 		return $line;
 	}
 	
 	/**
	 * 生成文件夹
	 * @param $path
	 */
	private function mkdirm($path){ 
		if (!file_exists($path)){ 
			$this->mkdirm(dirname($path)); 
			mkdir($path, 0777); 
		} 
	}
 	
	/**
	 * 解析内容模板
	 * @param $path
	 * @param $model
	 * @param $id
	 */
 	public function display($path,$model,$id){
 		$this->TplPath=SITEROOT . XG . TEMPLATEDIRECTORY . XG .TEMPLATEDIR . XG . $path;
		
 		if(!file_exists($this->TplPath)){
 			header("HTTP/1.1 404 Not Found2");
			exit();
 		}
 		$T_db=new htmldb();
		## 系统设置信息
		$SystemSettings=$T_db->table('setsys')->where('setsys0=1')->onerows();
		
		$contents=array();
		if($id!=false){
 			if($model=='onepagesys'){
 				$where=$model.'1='.$id;
 			}else{
 				$where=$model.'0='.$id;
 			}
 			$contents=$T_db->table($model)->where($where)->onerows();
		}
		
 		$this->TplSource=$this->readfile($this->TplPath);
		
 		## 创建编译目录
 		$t=pathinfo($path);
 		$cdir=CMSDATADIR . XG . 'templates' . XG . TEMPLATEDIR;
 		
 		$cdir.=($t['dirname']=='.')?'': XG .$t['dirname'];
		
		
		
 		$this->mkdirm($cdir);
 		
 		## 编译文件
		$this->TplCompile= $cdir.XG.$t['basename'].'.php';
	
 		$this->TplSource=$this->parse();
 		
 		file_put_contents($this->TplCompile,$this->TplSource);
		require $this->TplCompile;
 		
		
 	}
 	
 	/**
 	 * 模板解析
 	 */
 	private function parse(){
 		
 		#合并模板处理解析
 		$this->parse_include();
		
 		#模板数据
 		$tpl=$this->TplSource;
 		
 		#解析共用GET标签
 		$tpl=preg_replace_callback('#\{\$get\[(.*?)\]\}#i',array(&$this,'parse_get'),$tpl);
 		$tpl=preg_replace_callback('#\$get\[(.*?)\]#i',array(&$this,'parse_get'),$tpl);
		
		
		

		
 		
 		#解析变量并输出
 		$tpl=preg_replace('#\{\$(.*?)\}#i', '<?php echo $\1; ?>',$tpl);
 		
 		
 		#解析if elesif else
 		$tpl=preg_replace('#\{if\s+(.+?)\}#is', '<?php if(\1){ ?>', $tpl);
		$tpl=preg_replace('#\{elseif\s+(.+?)\}#is', '<?php }elseif(\1){ ?>', $tpl);
		$tpl=preg_replace('#\{else\}#is', '<?php }else{ ?>', $tpl);
		
		
		#解析结束标签
		$tpl=preg_replace_callback('#\{foreach(.*?)\}#i', array(&$this,'parse_foreach'), $tpl);
		$tpl=preg_replace('#\{\/(foreach|if|list)\}#i', '<?php }?>', $tpl);
		
		#解析调用函数
		$tpl=preg_replace('#\{func\s+(.*?)\}#i', '<?php echo \1 ?>',$tpl);
		
		#解析php 程序
		$tpl=preg_replace('#\{php\s+(.*?)\}#i', '<?php \1 ?>',$tpl);
		$tpl=preg_replace('#\{php\}(.*?)\{\/php\}#is', '<?php \1 ?>',$tpl);
		
		
		
		$tpl=preg_replace('/\{__(.*?)__\}/is', '<?php echo \1; ?>',$tpl);
		
		#解析内容标签
		$tpl=preg_replace_callback('/\{content(.*?) (.*?)\}/is',array(&$this,'parse_content'),$tpl);
		
		
		#解析列表标签
		$tpl=preg_replace_callback('/\{list(.*?) (.*?)\}/is',array(&$this,'parse_list'),$tpl);
		
		## 删除html注释
		//$tpl=preg_replace('#<!\-\-(.*?)\-\->}#is', '',$tpl);
		
		/*
		//$tpl=strtr($tpl,array("\r\n"=>''));
		//$tpl=strtr($tpl,array('	'=>''));
		*/
		
 		return $tpl;
 		
 		
 		
 	}
	
 	
 	/**
 	 * 解析列表标签
 	 */
 	public function parse_list($matches){
 		$larray=$this->parse_parameters($matches);
	 		$sqlparam=array(
	 			'table' => '',
	 			'where' => '',
	 			'field' => '*',
	 			'var'  => '',
	 			'page'  => '', #系统默认为page
	 			'order' => '',
	 			'msg' => '暂无数据!',
	 			'limit' => '' #系统默认为10
	 			//'sql'   => ''
	 		);

 			#表名
	 		if(isset($larray['table'])){
	 			$sqlparam['table']=$larray['table'];
	 		}else{
	 			throw new Exception('模板参数解析出错,缺少必要的参数 [table] <font color="red">'.$matches[0].'</font>');	
	 		}
	 		#条件
	 		if(isset($larray['where'])){
	 			$larray['where']=preg_replace('#\$(.*?)( |\))#i', '".$\1." ',$larray['where']);
	 			$sqlparam['where']=strtr($larray['where'],array('"'=>'\\"'));
	 			$sqlparam['where']=preg_replace('#\\\"\.\$(.*?)\.\\\"#i','".$\1."',$sqlparam['where']);
	 		}
	 		#变量
	 		if(isset($larray['var'])){
	 			$sqlparam['var']=strtr($larray['var'],array('$',''));
	 		}else{
	 			throw new Exception('模板参数解析出错,缺少必要的参数 [var]  <font color="red">'.$matches[0].'</font>');
	 		}
	 		#查询字段
	 		if(isset($larray['field'])){
	 			$sqlparam['field']=$larray['field'];
	 		}
	 		#分页标实
	 		if(isset($larray['page'])){
	 			$sqlparam['page']=$larray['page'];
	 		}
	 		#个数
	 		if(isset($larray['limit'])){
	 			$sqlparam['limit']=$larray['limit'];
	 		}
 			#排序
	 		if(isset($larray['msg'])){
	 			$sqlparam['msg']=$larray['msg'];
	 		}
 			#排序
	 		if(isset($larray['order'])){
	 			$sqlparam['order']=$larray['order'];
	 		}
			$sendpagelen = '';
			if(strlen($sqlparam['page'])>0){
				$sendpagelen = 'header("pagelength:".$T_db->pagelens);';	
			}
	 		$list_tpl='<?php
			if(!$T_db instanceof htmldb){$T_db=new htmldb();}
	 		$l_'.$sqlparam['var'].'=$T_db->table("'.$sqlparam['table'].'")->order("'.$sqlparam['order'].'")->where("'.$sqlparam['where'].'")->field("'.$sqlparam['field'].'")->limit("'.$sqlparam['limit'].'")->page("'.$sqlparam['page'].'")->selectlist();
					'.$sendpagelen.'
	 				$'.$sqlparam['var'].'_page=$T_db->htmlpageshow;
					$'.$sqlparam['var'].'_sql=$T_db->sql;
	 					if($l_'.$sqlparam['var'].'==null){
 							$l_'.$sqlparam['var'].'=array();
 							echo "'.$sqlparam['msg'].'";
 						}
 						$'.$sqlparam['var'].'_count=count($l_'.$sqlparam['var'].');
	 					foreach($l_'.$sqlparam['var'].' as $'.$sqlparam['var'].'_key=>$'.$sqlparam['var'].'){
	 		?>';
 			return $list_tpl;
 		
 	}
 	
 	
 	/**
 	 * 解析内容标签
 	 */
 	public function parse_content($matches){
 		
 		$parray=$this->parse_parameters($matches);
	
		
 		$sqlparam=array(
 			'table' => '',
 			'where' => '',
 			'field' => ' * ',
 			'var'  => '',
 			'limit' => '1'
 		);
 		
 		#表名
 		if(isset($parray['table'])){
 			$sqlparam['table']=$parray['table'];
 		}else{
 			$this->error('模板参数解析出错,缺少必要的参数 [table] <font color="red">'.$matches[0].'</font>');	
 		}
 		#条件
 		if(isset($parray['where']) || isset($parray['id'])){
 			if(isset($parray['id'])){
 				$sqlparam['where']='->id('.$parray['id'].')';
 			}else{
 				//$twhere=
 				
 				$parray['where']=preg_replace('#\$(.*?)( |\))#i', '".$\1." ',$parray['where']);
	 			$sqlparam['where']=strtr($parray['where'],array('"'=>'\\"'));
	 			$sqlparam['where']=preg_replace('#\\\"\.\$(.*?)\.\\\"#i','".$\1."',$sqlparam['where']);
 				$sqlparam['where']='->where("'.$sqlparam['where'].'")';
 			}
 			
 		}else{
 			$this->error('模板参数解析出错,缺少必要的参数  [where] 或者 [id] <font color="red">'.$matches[0].'</font>');
 		}
 		#name
 		if(isset($parray['var'])){
 			$sqlparam['var']=strtr($parray['var'],array('$',''));
 		}else{
 			$this->error('模板参数解析出错,缺少必要的参数 [var]  <font color="red">'.$matches[0].'</font>');
 		}
 		
 		#查询字段
 		if(isset($parray['field'])){
 			$sqlparam['field']=$parray['field'];
 		}
 		$detail_tpl='<?php 
 		if(!$T_db instanceof htmldb){$T_db=new htmldb();}
 		$'.$sqlparam['var'].'=$T_db->table("'.$sqlparam['table'].'")'.$sqlparam['where'].'->field("'.$sqlparam['field'].'")->limit("'.$sqlparam['limit'].'")->onerows();
 		?>';
 		
 		return $detail_tpl;
 		
 	}
 	
 	
 	/**
 	 * 解析 foreach 标签
 	 * @param $matches
 	 */
 	public function parse_foreach($matches){
		$tplcode=rtrim($matches[1]);
		$tplcodearray=explode(' ',$matches[1]);
		$temparray=array();
		foreach($tplcodearray as $value){
			if(strpos($value,'=')){
				$temparray[]=explode('=',$value);
			}
		}
		$keys=$fordata=$values=null;
		foreach($temparray as $key=>$value){
			if(strval($value[0])=='key'){
				$keys=$value[1];
			}elseif(strval($value[0])=='data'){
				$fordata=$value[1];
			}elseif(strval($value[0])=='value'){
				$values=$value[1];
			}
		}
		
		if($fordata==null || $value=null){
			$this->error('模板: <strong>' . $this->TplPath . '</strong> 解析错误');
		}
		
		if($keys==null){
			$tpl='<?php foreach('.$fordata.' as '.$values.'){ ?>';
		}else{
			$tpl='<?php foreach('.$fordata.' as '.$keys.'=>'.$values.'){ ?>';
		}
		return $tpl;
	}
	
 	/**
	 * 解析参数标签参数
	 */
	private function parse_parameters($param_str){
		$param=(isset($param_str[2]))?$param_str[2]:$param_str[1];
		if(preg_match_all('/((([a-z]+)="(.*?)")|(([a-z]+)=\'(.*?)\')){1}/i',$param,$p)){
			$paramarray=array();
			$pcount=count($p[0]);
			for($i=0;$i<$pcount;++$i){
				if(empty($p[2][$i]) && empty($p[5][$i])){
					$this->error('模板参数解析出错：<font color="red">'.$param_str[0].'</font>');
				}elseif(!empty($p[2][$i]) && substr($p[2][$i],-2,2)!='="'){
					$paramarray[strtolower($p[3][$i])]=$p[4][$i];
				}elseif(!empty($p[5][$i]) && substr($p[5][$i],-2,2)!="='"){
					$paramarray[strtolower($p[6][$i])]=$p[7][$i];
				}else{
					$this->error('模板参数解析出错:'.strtr($param_str[0],array($p[0][$i]=>'<font color="red">'.$p[0][$i].'</font>')));
				}
			}
			if(strlen($param_str[1])>0){
				$paramarray['var']=strtr($param_str[1],array(':'=>''));
			}
			return $paramarray;
		}else{
			$this->error('模板参数解析出错！<font color="red">'.$param_str[0].'</font>');
		}
	}
 	
 	
 	/**
 	 * 解析get标签
 	 * @param $matches
 	 */
 	private function parse_get($m){
 		$g=$_GET[strtr($m[1],array('"'=>'','\''=>''))];
 		if($g==false){
 			$g=0;
 		}
 		return $g;
 	}
 	
 	
 	/**
 	 * 合并模板（处理引用模板）
 	 */
 	private function parse_include(){
 		$this->TplSource = preg_replace_callback("/{include\s+file=('|\")?(.+?)('|\")?}/i",array(&$this,'get_parse_include'),$this->TplSource);
 	}
 	
	 /**
	 * 合并模板 回调引用模板的内容
	 * @param $m
	 */
	private function get_parse_include($m){	
		
		$t=strtr(SITEROOT . XG . 'template' . XG .TEMPLATEDIR . XG . $m[2],array('/'=>DIRECTORY_SEPARATOR));
		$r='';
		if(!file_exists($t)){
			$r = 'not template:'.$t;
		}else{
			$r=$this->readfile($t);
		}
		return $r;
		
	}
 	


}
